﻿using Cinemachine;
using UnityEngine;
#if ENABLE_INPUT_SYSTEM
using UnityEngine.InputSystem;
#endif

public abstract class CameraControl : MonoBehaviour
{
    enum ProjectionType
    {
        Perspective,
        Orthographic,
    }

    [Header("Zoom")]
    [Tooltip("相机拉近拉远 Zoom 当前值")]
    [SerializeField]
    protected float _distance = 20f;                      // 相机与lookAroudPos点的距离.
    [Tooltip("缩放灵敏度")]
    [SerializeField, Range(1f, 20f)]
    protected float _zoomSpeed = 10f;                     // 滚轮缩放速度.灵敏度
    [SerializeField]
    protected float _maxDistance = 100f;                  // 相机最远距离.
    [SerializeField]
    protected float _minDistance = 1f;                    // 相机最近距离.

    [Header("Drag Move")]
    [SerializeField]
    protected float _dragMoveSpeed = 1f;

    [Header("360° Rotate")]
    // Alt+鼠标拖动, 360度观察
    [SerializeField, Range(2f, 10f)]
    protected float _rotateSensitivity = 5f;                               // 旋转灵敏度.
    [SerializeField]
    protected Vector3 _lookAroundPos = Vector3.zero;

    [SerializeField]
    private ProjectionType _viewType;                                          // 当前视角.

    //[SerializeField]
    //protected float _rotationSpeed;


    // 选中物体聚焦
    private GameObject _selectedObj = null;                              // 选中的物体.
    private float _raycastMaxDistance = 1000f;
    private LayerMask _raycastLayerMask;
    private RaycastHit _raycastHit;

    protected static CameraControl _instance;

    protected Camera TargetCamera;
    [SerializeField] protected CinemachineVirtualCamera _cinemachineVirtualCamera;
    protected virtual bool MiddleMouseButton
    {
        get
        {
#if ENABLE_INPUT_SYSTEM && !ENABLE_LEGACY_INPUT_MANAGER
            return Mouse.current.middleButton.IsPressed();
#else
	        return Input.GetMouseButtonDown(2);
#endif
        }
    }
    public Vector2 MousePosition
    {
        get
        {
#if ENABLE_INPUT_SYSTEM && !ENABLE_LEGACY_INPUT_MANAGER
            return Mouse.current.position.ReadValue();
#else
            return Input.mousePosition;
#endif
        }
    }
#if ENABLE_INPUT_SYSTEM && !ENABLE_LEGACY_INPUT_MANAGER
    protected virtual float zoomDelta { get => Mouse.current.scroll.ReadValue().normalized.y; }
#else
	float zoomDelta = Input.GetAxis("Mouse ScrollWheel");
#endif
    /// <summary>
    /// Whether the singleton camera controls are locked.
    /// </summary>
    public static bool Locked
    {
        set => _instance.enabled = !value;
    }

    /// <summary>
    /// Validate the position of the singleton camera.
    /// </summary>
    public static void ValidatePosition() => _instance.AdjustPosition(0f, 0f);
    protected virtual void OnEnable()
    {
        _instance = this;
        Init();
        ValidatePosition();
    }
    protected virtual void OnDisable()
    {

    }
    void Update()
    {


        //滚轮缩放
        AdjustZoom(zoomDelta);

        //float rotationDelta = Input.GetAxis("Rotation");
        //if (rotationDelta != 0f) {
        //	AdjustRotation(rotationDelta);
        //}

        //按键移动。
        //#if ENABLE_INPUT_SYSTEM && !ENABLE_LEGACY_INPUT_MANAGER
        //        var delata = Mouse.current.position.ReadValue();

        //        float xDelta = delata.x;
        //        float zDelta = delata.y;
        //#else	
        //		float xDelta = Input.GetAxis("Horizontal");
        //		float zDelta = Input.GetAxis("Vertical");
        //#endif

        //        if (xDelta != 0f || zDelta != 0f)
        //        {
        //            AdjustPosition(xDelta, zDelta);
        //        }
        OnUpdate();
    }
    public virtual void OnUpdate()
    {

    }
    /// <summary>
    /// 初始化.
    /// </summary>
    protected virtual void Init()
    {
        //TargetCamera = GetComponent<Camera>();
        TargetCamera = Camera.main;
        //raycastLayerMask = 1 << LayerMask.NameToLayer("Default");

        RecalcDistance();
        //CalculateProjMatrix();                  // 获取相机默认矩阵.
        ResetLookAroundPos();                   // 重置观察中心.
        //LoadCursorTexture();                    // 加载鼠标图标.
    }

    /// <summary>
    /// 计算距离.
    /// </summary>
    private void RecalcDistance()
    {
        Vector3 checkFarPos = TargetCamera.transform.position + TargetCamera.transform.rotation * (Vector3.forward * 1000);
        if (Physics.Linecast(TargetCamera.transform.position, checkFarPos, out _raycastHit))
        {
            // 如果相机中心有物体，则以物体到相机为距离
            _distance = _raycastHit.distance;
            if (_selectedObj == null)
            {
                _selectedObj = _raycastHit.collider.gameObject;
            }
        }
    }

    /// <summary>
    /// 重置观察中心(观察中心在相机的前方).
    /// </summary>
    protected void ResetLookAroundPos()
    {
        _lookAroundPos = transform.position + transform.rotation * (Vector3.forward * _distance);
    }


    protected abstract void AdjustZoom(float delta);
    protected abstract void AdjustRotation(float delta);
    protected abstract void AdjustPosition(float xDelta, float zDelta);
}
/// <summary>
/// need cenimachine ,挂到要控制的物体
/// </summary>
public class MapCamera : CameraControl
{

    protected override void Init()
    {
        base.Init();
        _targetZoomDistance = _distance;
        HandleCameraZoom_OrthographicSize(_distance);
    }
    public override void OnUpdate()
    {
        Drag();
    }

    #region 拖动

    private bool isDraging = false;
    private Vector2 lastMousePos;

    /// <summary>
    /// 拖动.
    /// </summary>
    /// <remark>长按鼠标中键拖动</remark>
    private void Drag()
    {
        // 鼠标中键拖动相机.
        if (MiddleMouseButton)
        {
            if (isDraging == false)
            {
                isDraging = true;
                // 设置小手指针.
                //SetCursor(CursorType.HAND);
                lastMousePos = MousePosition;
            }
        }
        else
        {
            isDraging = false;
            //恢复默认指针.
            //SetCursor(CursorType.DEFAULT);
        }
        if (isDraging)
        {
            Vector2 newMousePos = MousePosition;
            Vector2 delta = newMousePos - lastMousePos;
            transform.position += CalcDragLength(TargetCamera, delta, _distance);
            lastMousePos = newMousePos;

            // 相机移动，重新设置目标位置.
            ResetLookAroundPos();
        }
    }

    /// <summary>
    /// 计算拖拽距离.
    /// </summary>
    /// <param name="camera">相机</param>
    /// <param name="mouseDelta">鼠标移动距离</param>
    /// <param name="distance">相机距离观察物体的距离</param>
    private Vector3 CalcDragLength(Camera camera, Vector2 mouseDelta, float distance)
    {
        float rectHeight = -1;
        float rectWidth = -1;
        if (camera.orthographic)
        {
            rectHeight = 2 * camera.orthographicSize;
            //rectWidth = rectHeight / camera.aspect;
        }
        else
        {
            rectHeight = 2 * distance * Mathf.Tan(camera.fieldOfView * 0.5f * Mathf.Deg2Rad);
        }
        rectWidth = Screen.width * rectHeight / Screen.height;
        Vector3 moveDir = -rectWidth / Screen.width * mouseDelta.x * camera.transform.right - rectHeight / Screen.height * mouseDelta.y * camera.transform.up;
        moveDir.y = 0;
        return moveDir;
    }

    #endregion

    #region 拉近拉远

    /// <summary>
    /// 拉近拉远.
    /// </summary>
    /// <remarks>鼠标滚轮滚动，向上滚动拉近相机，向下滚动拉远相机</remarks>
    /// 
    private void HandleCameraZoom_OrthographicSize(float targetOrthographicSize)
    {
        _cinemachineVirtualCamera.m_Lens.OrthographicSize = targetOrthographicSize;
    }

    #endregion
    [Tooltip("滚轮的灵敏度")]
    [SerializeField]
    float _zoomSensibility=1;

    private float _targetZoomDistance;
    protected override void AdjustZoom(float delta)
    {
        var scrollWheelValue = delta * _zoomSensibility;
        if (!Mathf.Approximately(scrollWheelValue, 0f))//防抖
        {

            // scrollWheelValue：滚轮向上为+ 向下为-
            // 同时滚轮向上，拉近相机；滚轮向下，拉远相机
            //_distance -= scrollWheelValue;
            _targetZoomDistance = _distance - scrollWheelValue;
            _targetZoomDistance = Mathf.Clamp(_targetZoomDistance, _minDistance, _maxDistance);
            //transform.position = _lookAroundPos - transform.rotation * (Vector3.forward * _distance);
        }
        if (Mathf.Approximately(_targetZoomDistance, _distance))
        {
            return;
        }
        //到目标值的速度
        _distance = Mathf.Lerp(_distance, _targetZoomDistance, Time.deltaTime * _zoomSpeed);
        HandleCameraZoom_OrthographicSize(_distance);


    }

    protected override void AdjustRotation(float delta)
    {

    }

    protected override void AdjustPosition(float xDelta, float zDelta)
    {

    }
}